﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Scryber.Drawing;
using Scryber.Styles;

namespace Scryber.Components
{
    [PDFParsableComponent("Polygram")]
    public class PDFPolygram : PDFPolygonBase
    {


        /// <summary>
        /// Gets or sets the number of vertices in the polygram
        /// </summary>
        [PDFAttribute("vertex-count", Scryber.Styles.PDFStyle.PDFStylesNamespace)]
        public int VertexCount
        {
            get { return this.Style.Shape.VertexCount; }
            set { this.Style.Shape.VertexCount = value; }
        }


        /// <summary>
        /// Gets the the step offset when linking the polygram
        /// </summary>
        [PDFAttribute("vertex-step", Scryber.Styles.PDFStyle.PDFStylesNamespace)]
        public int VertexStep
        {
            get { return this.Style.Shape.VertexStep; }
            set { this.Style.Shape.VertexStep = value; }
        }


        public PDFPolygram()
            : this(PDFObjectTypes.ShapePolygram)
        {
        }

        public PDFPolygram(PDFObjectType type)
            : base(type)
        {
        }


        
        
        protected override Drawing.PDFPoint[] GetPoints(Drawing.PDFRect bounds, PDFShapeStyle style)
        {
            if (this.VertexCount > 4)
            {
                if (this.StepCount >= VertexCount)
                    throw new PDFException(Errors.StepCountCannotBeGreaterThanVertexCount);

                PDFUnit radius = (bounds.Width / 2.0);
                PDFPoint centre = new PDFPoint(radius, radius);
                double rotation = this.Rotation;

                return this.GetRegularPolygonPoints(centre, radius, radius, this.VertexCount, rotation);
            }
            else if (this.VertexCount != 0) //between 1 and 3 sides is invalid.
                throw new PDFException(Errors.CannotCreatePolygramWithLessThan5Sides, null);
            else
                return new PDFPoint[] { };
        }


        protected virtual void BuildPolygramPath(PDFGraphicsPath path, PDFPoint[] points, int step)
        {
            bool[] visited = new bool[points.Length];
            int loopcount = 0;
            int firstFree = 0;

            //checks the integer array of see if everyone has been covered
            Func<bool> visitedAll = delegate()
            {
                for (int i = 0; i < visited.Length; i++)
                {
                    if (visited[i] == false)
                    {
                        firstFree = i;
                        return false;
                    }
                }
                return true;
            };
            
            while (!visitedAll() && loopcount < 10)
            {
                if (path.HasCurrentPath == false)
                    path.BeginPath();

                int index = firstFree; //firstFree is set from the visitedAll method
                PDFPoint first = points[index];
                PDFPoint current = first;

                path.MoveTo(current);
                do
                {
                    index += step;
                    if (index >= points.Length)
                        index -= points.Length;

                    current = points[index];
                    visited[index] = true; //mark the point as visited.
                    if (current == first)
                        path.ClosePath(false);
                    else
                        path.LineTo(current);
                    

                } while (current != first);

                path.EndPath();

                loopcount++;
            }
        }



    }
}
